package com.ewili.x.special.service.strategy.impl;

import com.ewili.framework.utils.DateUtils;
import com.ewili.framework.utils.MathUtils;
import com.ewili.x.special.comparator.HisRecordComparator;
import com.ewili.x.special.dao.inter.HisRecordDao;
import com.ewili.x.special.dao.inter.ValueDao;
import com.ewili.x.special.entity.HisRecord;
import com.ewili.x.special.entity.Value;
import com.ewili.x.special.service.strategy.inter.StrategyService;
import com.ewili.x.special.vo.ExecsVo;
import com.ewili.x.special.vo.KlineVo;
import com.ewili.x.special.vo.StrategyVo;
import com.ewili.x.special.vo.ValueVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Service
public class StrategyServiceImpl implements StrategyService {

    @Autowired
    private HisRecordDao hisRecordDao;

    @Autowired
    private ValueDao valueDao;

    @Override
    public List<StrategyVo> newStockStrategy() {
        List<HisRecord> stockNDates = hisRecordDao.findStockCodeMinTradeDate();
        if (CollectionUtils.isEmpty(stockNDates)) {
            return Collections.emptyList();
        }

        List<StrategyVo> strategyVos = new ArrayList<StrategyVo>();

        for (HisRecord stockNDate : stockNDates) {
            //持有十个月
            Date endDate = DateUtils.addMonths(stockNDate.getDate(), 10);
            // StrategyVo strategyVo = dataAnaysis(stockNDate.getStockCode(), stockNDate.getDate(), endDate);
            StrategyVo strategyVo = maxDowndataAnaysis(stockNDate.getStockCode(), stockNDate.getDate(), endDate);
            strategyVos.add(strategyVo);
        }
        return strategyVos;
    }

    @Override
    public List<StrategyVo> newStockDownStrategy() {
        List<String> daysOnMarketStocks = hisRecordDao.findDaysMarketStocks(360L);
        List<StrategyVo> strategyVos = new ArrayList<>();
        for (String stockCode : daysOnMarketStocks) {
            List<HisRecord> hisRecords = hisRecordDao.findHisRecordByStockCodeOrderByDateDesc(stockCode);
            HisRecord maxHisRecord = Collections.max(hisRecords, new HisRecordComparator());
            double percent = MathUtils.percent(hisRecords.get(0).getTotalValue(), maxHisRecord.getTotalValue(), 3);
            if (percent > -60) {
                continue;
            }
            StrategyVo strategyVo = new StrategyVo();
            strategyVo.setStockCode(stockCode);
            strategyVo.setMinPercent(percent);
            strategyVo.setBuyDate(hisRecords.get(0).getDate());
            strategyVos.add(strategyVo);
        }
        return strategyVos;
    }

    @Override
    public List<StrategyVo> shareStrategy() {

        return null;
    }

    @Override
    public List<KlineVo> findKlines() {
        List<KlineVo> klineVos = new ArrayList<>();
        List<HisRecord> hisRecords = hisRecordDao.findHisRecordByStockCodeOrderByDateAsc("000980");
        for (HisRecord hisRecord : hisRecords) {
            KlineVo klineVo = new KlineVo();
            klineVo.setShizhi(hisRecord.getTotalValue());
            klineVo.setDate(hisRecord.getDate());
            klineVos.add(klineVo);
        }
        return klineVos;
    }

    @Override
    public List<ValueVo> findValues() {
        List<Value> values = valueDao.findByCodeOrderByDateAsc("000980");
        List<ValueVo> valueVos = new ArrayList<>();
        for (Value value : values) {
            ValueVo valueVo = new ValueVo();
            valueVo.setPb(value.getPb());
            valueVo.setDate(value.getDate());
            valueVos.add(valueVo);
        }
        return valueVos;
    }

    @Override
    public List<ExecsVo> findExecs() {
        List<Object[]> vos = hisRecordDao.findHisRecordExecs("300369");

        List<ExecsVo> execsVos = new ArrayList<>();
        for (Object[] object : vos) {
            ExecsVo execsVo = new ExecsVo();
            execsVo.setStockCode(object[0].toString());
            execsVo.setDate(object[1].toString());

            execsVo.setSubDis(Double.valueOf(object[2].toString()));
            if (object[3] == null) {
                execsVo.setSum(0.0d);
            } else {
                execsVo.setSum(Double.valueOf(object[3].toString()));
            }
            if (object[4] == null) {
                execsVo.setSum(0.0d);
            } else {
                execsVo.setPb(Double.valueOf(object[4].toString()));
            }
            execsVos.add(execsVo);
        }
        return execsVos;
    }


    @Override
    public List<ExecsVo> findWholdExecs() {
        List<Object[]> vos = hisRecordDao.findWholeMarketsExecs();

        List<ExecsVo> execsVos = new ArrayList<>();
        for (Object[] object : vos) {
            ExecsVo execsVo = new ExecsVo();
            execsVo.setDate(object[0].toString());

            if (object[1] == null) {
                execsVo.setSubDis(0.0d);
            } else {
                execsVo.setSubDis(Double.valueOf(object[1].toString()));
            }
            if (object[2] == null) {
                execsVo.setSum(0.0d);
            } else {
                execsVo.setSum(Double.valueOf(object[2].toString()));
            }
            if (object[3] == null) {
                execsVo.setPb(0.0d);
            } else {
                execsVo.setPb(Double.valueOf(object[3].toString()));
            }
            if (object[4] == null) {
                execsVo.setHyDisperson(0.0d);
            } else {
                execsVo.setHyDisperson(Double.valueOf(object[4].toString()));
            }
            execsVos.add(execsVo);
        }
        return execsVos;
    }

    private StrategyVo maxDowndataAnaysis(String stockCode, Date startDate, Date endDate) {
        List<HisRecord> hisRecords = hisRecordDao.findHisRecordByStockCodeAndDateAferAndDateBefore(stockCode, startDate, endDate);
        StrategyVo vo = new StrategyVo();

        if (hisRecords.isEmpty()) {
            return vo;
        }

        //得到最大值序列
        List<HisRecord> hisRecordMaxs = new ArrayList<>();
        Double maxTotalValue = hisRecords.get(0).getTotalValue();
        for (HisRecord hisRecord : hisRecords) {
            if (maxTotalValue < hisRecord.getTotalValue()) {
                maxTotalValue = hisRecord.getTotalValue();
                hisRecordMaxs.add(hisRecord);
            }
        }

        //得到最小值序列
        List<HisRecord> hisRecordsMins = new ArrayList<>();

        for (int i = 0; i < hisRecordMaxs.size(); i++) {
            int startIndex = hisRecords.indexOf(hisRecordMaxs.get(i));

            List<HisRecord> subHisRecords = hisRecords.subList(startIndex, hisRecords.size() - 1);

            if (CollectionUtils.isEmpty(subHisRecords)) {
                hisRecordsMins.add(hisRecords.get(startIndex));
            } else {
                HisRecord minHisRecord = Collections.min(subHisRecords, new HisRecordComparator());
                hisRecordsMins.add(minHisRecord);
            }
        }

        StrategyVo strategyVo = new StrategyVo();

        double endPercent = 0.0d;
        for (int j = 0; j < hisRecordMaxs.size(); j++) {
            HisRecord maxHisRecord = hisRecordMaxs.get(j);
            HisRecord minHisRecord = hisRecordsMins.get(j);

            double minPercent = 0.0d;

            if (maxHisRecord.getTotalValue() != 0) {
                minPercent = MathUtils.percent(minHisRecord.getTotalValue(), maxHisRecord.getTotalValue(), 2);
            }

            if (endPercent > minPercent) {
                endPercent = minPercent;
            }
            strategyVo.setMinPercent(endPercent);
            strategyVo.setStockCode(stockCode);
            strategyVo.setMinDate(minHisRecord.getDate());
        }
        return strategyVo;
    }

    private StrategyVo dataAnaysis(String stockCode, Date startDate, Date endDate) {
        List<HisRecord> hisRecords = hisRecordDao.findHisRecordByStockCodeAndDateAferAndDateBefore(stockCode, startDate, endDate);

        StrategyVo vo = new StrategyVo();

        if (hisRecords.isEmpty()) {
            return vo;
        }

        HisRecord tradeRecord = hisRecords.get(0);

        HisRecord maxHisRecord = Collections.max(hisRecords, new HisRecordComparator());
        HisRecord minHisRecord = Collections.min(hisRecords, new HisRecordComparator());
        if (DateUtils.isSameDay(maxHisRecord.getDate(), tradeRecord.getDate())) {
            return vo;
        }
        double maxPercent = MathUtils.percent(maxHisRecord.getTotalValue(), tradeRecord.getTotalValue(), 2);
        double minPercent = MathUtils.percent(minHisRecord.getTotalValue(), tradeRecord.getTotalValue(), 2);

        vo.setBuyDate(tradeRecord.getDate());
        vo.setMaxDate(maxHisRecord.getDate());
        vo.setMinDate(minHisRecord.getDate());
        vo.setMaxPercent(maxPercent);
        vo.setMinPercent(minPercent);
        vo.setStockCode(stockCode);

        return vo;
    }
}
